package com.example.jopewars;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.*;

import org.w3c.dom.*;
import org.xml.sax.SAXException;

public class GameEngine {

	private static GameEngine instance;

	private Location currentLocation;

	private int turnNumber;

	private long cashAmount;

	private long debtAmount;

	private long bankAmount;

	private int healthAmount;

	private int numberOfBitches;

	private int numberOfGuns;

	private int spaceAvailable;

	private Map<String, DrugEntry> drugs;

	private List<GameStateChangedListener> listeners;

	private GameEngine() {
		listeners = new ArrayList<GameStateChangedListener>();
		initialize();
	}

	private void initialize() {
		turnNumber = 0;
		bankAmount = 0;
		// cashAmount = 2000;
		// debtAmount = 5500;
		numberOfBitches = 8;
		numberOfGuns = 0;
		spaceAvailable = 100;
		healthAmount = 100;

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		try {
			DocumentBuilder db = dbf.newDocumentBuilder();
			File file = new File("bin/com/example/jopewars/Config.xml");
			if (file.exists()) {
				Document doc = db.parse(file);
				System.out.println("Parsing configuration file...");
				NodeList nodes = doc.getElementsByTagName("general");
				parseGeneralNodes(nodes.item(0));
				nodes = doc.getElementsByTagName("locations");
				parseLocationNodes(nodes.item(0));
				nodes = doc.getElementsByTagName("drugs");
				parseDrugNodes(nodes.item(0));
			}
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	private void parseDrugNodes(Node drugsNode) {
		System.out.println("Parsing Drug Node");
		NodeList drugs = drugsNode.getChildNodes();
		for (int i = 0; i < drugs.getLength(); i++) {
			Node drugNode = drugs.item(i);
			if (drugNode.getNodeName().equals("drug")) {
				NodeList settings = drugNode.getChildNodes();
				Drug drug = new Drug();

				for (int j = 0; j < settings.getLength(); j++) {
					Node setting = settings.item(j);
					if (setting.getNodeName().equals("name")) {
						String name = setting.getFirstChild().getNodeValue();
						drug.setName(name);
					} else if (setting.getNodeName().equals("min_price")) {
						String s = setting.getFirstChild().getNodeValue();
						int min = Integer.parseInt(s);
						drug.setMinPrice(min);
					} else if (setting.getNodeName().equals("max_price")) {
						String s = setting.getFirstChild().getNodeValue();
						int max = Integer.parseInt(s);
						drug.setMaxPrice(max);
					} else if (setting.getNodeName().equals("cheap")) {
						String s = setting.getFirstChild().getNodeValue();
						boolean cheap = Boolean.parseBoolean(s);
						drug.setCheap(cheap);
					} else if (setting.getNodeName().equals("expensive")) {
						String s = setting.getFirstChild().getNodeValue();
						boolean expensive = Boolean.parseBoolean(s);
						drug.setExpensive(expensive);
					} else if (setting.getNodeName().equals("cheap_str")) {
						String s = setting.getFirstChild().getNodeValue();
						drug.setCheapMessage(s);
					}
				}

				DrugManager.getDrugs().add(drug);
			}
		}
	}

	private void parseLocationNodes(Node node) {
		System.out.println("Parsing Locations Node");
		NodeList locations = node.getChildNodes();

		for (int i = 0; i < locations.getLength(); i++) {
			Node location = locations.item(i);

			if (location.getNodeName().equals("location")) {
				NodeList settings = location.getChildNodes();
				Location loc = new Location();

				for (int j = 0; j < settings.getLength(); j++) {
					Node setting = settings.item(j);

					if (setting.getNodeName().equals("name")) {
						loc.setName(setting.getFirstChild().getNodeValue());
					}

					if (setting.getNodeName().equals("police_presence")) {
						int police_presence = Integer.parseInt(setting
								.getFirstChild().getNodeValue());
						loc.setPolicePresencePercentage(police_presence);
					}

					if (setting.getNodeName().equals("max_drugs")) {
						int maxDrugs = Integer.parseInt(setting.getFirstChild()
								.getNodeValue());
						loc.setMaxDrugs(maxDrugs);
					}

					if (setting.getNodeName().equals("min_drugs")) {
						int minDrugs = Integer.parseInt(setting.getFirstChild()
								.getNodeValue());
						loc.setMinDrugs(minDrugs);
					}
				}

				Location.getLocations().add(loc);
			}
		}
	}

	private void parseGeneralNodes(Node generalNode) {
		System.out.println("Parsing General Node");
		NodeList nodes = generalNode.getChildNodes();
		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);
			if (node.getNodeName().equals("cash")) {
				int cash = Integer
						.parseInt(node.getFirstChild().getNodeValue());
				this.cashAmount = cash;
			}
			if (node.getNodeName().equals("debt")) {
				int debt = Integer
						.parseInt(node.getFirstChild().getNodeValue());
				this.debtAmount = debt;
			}
		}
	}

	public static GameEngine getInstance() {
		if (instance == null) {
			instance = new GameEngine();
		}
		return instance;
	}

	public Location getLocation() {
		return currentLocation;
	}

	public void setLocation(Location location) {
		this.currentLocation = location;
	}

	public int getTurnNumber() {
		return turnNumber;
	}

	public void setTurnNumber(int turnNumber) {
		this.turnNumber = turnNumber;
	}

	public long getCashAmount() {
		return cashAmount;
	}

	public void setCashAmount(long cashAmount) {
		this.cashAmount = cashAmount;
	}

	public long getDebtAmount() {
		return debtAmount;
	}

	public void setDebtAmount(long debtAmount) {
		this.debtAmount = debtAmount;
	}

	public long getBankAmount() {
		return bankAmount;
	}

	public void setBankAmount(long bankAmount) {
		this.bankAmount = bankAmount;
	}

	public int getHealthAmount() {
		return healthAmount;
	}

	public void setHealthAmount(int healthAmount) {
		this.healthAmount = healthAmount;
	}

	public int getNumberOfBitches() {
		return numberOfBitches;
	}

	public void setNumberOfBitches(int numberOfBitches) {
		this.numberOfBitches = numberOfBitches;
	}

	public int getNumberOfGuns() {
		return numberOfGuns;
	}

	public void setNumberOfGuns(int numberOfGuns) {
		this.numberOfGuns = numberOfGuns;
	}

	public int getSpaceAvailable() {
		return spaceAvailable;
	}

	public void setSpaceAvailable(int spaceAvailable) {
		this.spaceAvailable = spaceAvailable;
	}

	public Map<String, DrugEntry> getDrugs() {
		return drugs;
	}

	public void setDrugs(Map<String, DrugEntry> drugs) {
		this.drugs = drugs;
	}

	public void nextTurn(Location newLocation) {
		turnNumber++;
		bankAmount = (long) (bankAmount * 1.06);
		debtAmount = (long) (debtAmount * 1.10);

		currentLocation = newLocation;
		generateDrugPrices();
		notifyGameStateChanged();
	}

	private void generateDrugPrices() {
		int min = currentLocation.getMinDrugs();
		int max = currentLocation.getMaxDrugs();
		List<Drug> drugs = DrugManager.getDrugsForLocation(max, min);
		currentLocation.setDrugs(drugs);
	}

	public void addGameStateChangedListener(GameStateChangedListener listener) {
		listeners.add(listener);
	}

	protected void notifyGameStateChanged() {
		for (GameStateChangedListener list : listeners) {
			list.gameStateChanged();
		}
	}

	public void startNewGame() {

	}

}
